/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package model.creature.plant;

import java.awt.Image;
import java.util.ArrayList;
import model.creature.AttackableCreature;
import model.creature.monster.Monster;
import model.game.GameInterface;
import model.map.cell.PlantableCell;

/**
 *
 * @author dolphinigle
 */
public abstract class AOEAttackerPlant extends MultiHarvestPlant
  implements AttackableCreature {

  private int next_attack_;

  /**
   * Constructor
   */
  public AOEAttackerPlant(GameInterface game, PlantableCell cell) {
    super(game, cell);
    next_attack_ = 0;
  }

  /**
   * Advances time and attack monsters
   */
  @Override
  public void advanceTime() {
    if (!canAttack()) return;
    if (next_attack_ > 0) {
      --next_attack_;
    }
    if (next_attack_ != 0) {
      return;
    }
    ArrayList<Monster> monsters =
            (ArrayList<Monster>)game_.getCreatures().getMonsters().getAllMonsters().clone();
    int maxcnt = getAttackCount();
    for (Monster monster : monsters) {
      if (maxcnt <= 0) break;
      int manhattandistance = Math.abs(monster.getCell().getX() -
              getCell().getX()) + Math.abs(monster.getCell().getY() -
              getCell().getY());
      if (manhattandistance <= getRadius()) {
        --maxcnt;
        game_.addMessage(this.getName() + " attacked " + monster.getName() +
                " for " + getPower() + " damage.");
        monster.inflictDamage(getPower());
        next_attack_ = getAttackSpeed();
      }
    }
  }
  
  /**
   * Returns true if this plant can attack at this stage
   *
   * Set by default that this plant attacks when it's harvestable
   */
  public boolean canAttack() {
    return isHarvestable();
  }
  /**
   * Retrieves the fruit name from this plant when harvested
   */
  @Override
  protected abstract String getFruitName();

  /**
   * Retrieves the days required to go from seed to mature
   */
  @Override
  protected abstract int timeToMature();

  /**
   * Retrieves the days before this plant dies
   */
  @Override
  protected abstract int timeToDie();

  /**
   * Retrieves the days before this plant can be harvested from mature state,
   * having beeing harvested harvest_count times before
   */
  @Override
  protected abstract int timeToHarvest(int harvest_count);

  /**
   * Retrieves the HP of this plant at the given level
   * level can be accessed through getLevel()
   */
  @Override
  protected abstract int getHPAtCurrentLevel();

  /**
   * Returns true iff plant can be upgraded again now
   * It's current level is given in getLevel()
   */
  @Override
  public abstract boolean canUpgrade();

  /**
   * Retrieves the price to upgrade this plant's level
   * It's current level is given in getLevel()
   * @requires canUpgrade()
   */
  @Override
  public abstract int getUpgradeCost();

   /**
   * Returns the image sprite of this plant
   */
  @Override
  public abstract Image getImage();

  /**
   * Returns the name of this plant
   * Primary Key
   */
  @Override
  public abstract String getName();

  /**
   * Return the season only during this season this plant may grow
   */
  @Override
  public abstract String getSeason();

  /**
   * Returns the description of this plant
   */
  @Override
  public abstract String getDescription();

  /**
   * Determines the dmaage done by a creature when attacking
   */
  @Override
  public abstract int getPower();

  /**
   * Returns the radius of this plant's attacks
   *
   * I.e., this plant attack at most plantAttackCount() monsters whose
   * manhattan distance with this plant is less than or equal getRadius()
   */
  public abstract int getRadius();

  /**
   * Returns the number of shots this plant performs each time.
   */
  public abstract int getAttackCount();

  /**
   * Returns the attack speed of this plant.
   *
   * I.e., attacks every X turns
   */
  public abstract int getAttackSpeed();

}
